package com.lambkit.core;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ClassUtil;
import com.lambkit.core.annotion.App;
import com.lambkit.core.annotion.ScanPackage;
import com.lambkit.core.pipeline.PipeLineContext;
import com.lambkit.core.pipeline.Valve;
import com.lambkit.util.Printer;

import java.util.List;
import java.util.Set;

/**
 * @author yangyong(孤竹行)
 */
public class AppScanValve extends Valve {
    @Override
    public void invoke(PipeLineContext context, boolean isHandled) {
        Class<?> target = Lambkit.context().getTargetClass();
        String[] args = context.getAttr("args");
        List<Class<? extends LambkitApp>> lambkitAppClassList = CollUtil.newArrayList();
        if(target == null) {
            Printer.print(this, "starter", "-- ***** -- no target class");
        }
        boolean hasScanApp = true;
        if(target!=null) {
            App appAnno = target.getAnnotation(App.class);
            if (appAnno != null) {
                Class<? extends LambkitApp>[] appClasses = appAnno.value();
                if (appClasses != null && appClasses.length > 0) {
                    hasScanApp = false;
                    for (int i = 0; i < appClasses.length; i++) {
                        Class<? extends LambkitApp> appClass = appClasses[i];
                        lambkitAppClassList.add(appClass);
                        Printer.print(this, "starter", "Lambkit App Annotation {}", appClass.getName());
                    }
                }
            }
        }

        if(hasScanApp) {
            LambkitServer server = Lambkit.context().getBean(LambkitServer.class);
            if (server != null) {
                App appAnnotation = server.getClass().getAnnotation(App.class);
                if (appAnnotation != null) {
                    Class<? extends LambkitApp>[] appClasses = appAnnotation.value();
                    if (appClasses != null && appClasses.length > 0) {
                        hasScanApp = false;
                        for (int i = 0; i < appClasses.length; i++) {
                            Class<? extends LambkitApp> appClass = appClasses[i];
                            lambkitAppClassList.add(appClass);
                            Printer.print(this, "starter", "LambkitServer App Annotation {}", appClass.getName());
                        }
                    }
                }
            } else {
                Printer.print(this, "starter", "LambkitServer is null");
            }
        }
        if(hasScanApp && target != null) {
            //搜索LambkitApp的之类
            List<String> packages = null;
            ScanPackage scanPackage = target.getAnnotation(ScanPackage.class);
            if(scanPackage != null) {
                String[] pkgs = scanPackage.value();
                if(pkgs!=null && pkgs.length > 0) {
                    packages = CollUtil.newArrayList(pkgs);
                }
            }
            if(packages == null) {
                packages = CollUtil.newArrayList(ClassUtil.getPackage(target));
            }
            for (String packageName : packages) {
                Set<Class<?>> lkApps = ClassUtil.scanPackageBySuper(packageName, LambkitApp.class);
                if(lkApps!=null) {
                    for(Class lkApp : lkApps) {
                        Class<? extends LambkitApp> lambkitApp = lkApp;
                        lambkitAppClassList.add(lambkitApp);
                        Printer.print(this, "starter", "LambkitApp scan {}", lambkitApp.getName());
                    }
                }
            }
        }
        context.setAttr("lambkitAppClassList", lambkitAppClassList);
        next(context, isHandled);
    }
}
